package com.pap.rabbitmq.trans.aop;

import com.pap.rabbitmq.data.RabbitMetaMessage;
import com.pap.rabbitmq.trans.annotation.TransRabbitMQAnnotation;
import com.pap.rabbitmq.trans.coordinator.ICoordinator;
import com.pap.rabbitmq.trans.send.TransRabbitSender;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import java.text.SimpleDateFormat;
import java.util.Date;

/**
 * 封装消息发送类 面向切面编程，封装消息发送，并且维护第三方守护进程
 *
 * @Auther: alexgaoyh
 * @Date: 2018/12/3 16:44
 * @Description:
 */
@Component
@Aspect
public class TransSenderAOP {

    @Autowired
    TransRabbitSender transRabbitSender;

    @Autowired
    ICoordinator iCoordinator;

    @Autowired
    ApplicationContext applicationContext;

    /**
     * 定义注解类型的切点，只要方法上有该注解，都会匹配
     */
    @Pointcut("@annotation(transRabbitMQAnnotation)")
    public void annotationSender1(TransRabbitMQAnnotation transRabbitMQAnnotation) {

    }

    @Around("annotationSender1(rd)")
    public void sendMsg(ProceedingJoinPoint joinPoint, TransRabbitMQAnnotation rd) throws Throwable {
        // TODO logger.info("==> custom mq annotation,rd"+ rd);
        System.out.println("============> custom mq annotation," + rd);
        String exchange = rd.exchange();
        String bindingKey = rd.bindingKey();
        String dbCoordinator = rd.dbCoordinator();
        String bizName = rd.bizName() + "," + getCurrentDateTime();
        ICoordinator coordinator = null;

        try {
            coordinator = (ICoordinator) applicationContext.getBean(dbCoordinator);
        } catch (Exception ex) {
            // TODO logger.error("无对应的消息存储类，事务执行终止");
            return;
        }

        /**
         * 发送前暂存消息
         */
        coordinator.setMsgPrepare(bizName);

        Object returnObj = null;
        /**
         * 执行业务函数
         */
        try {
            returnObj = joinPoint.proceed();
        } catch (Exception ex) {
            // TODO logger.error("业务执行失败,业务名称:" + bizName);
            throw ex;
        }

        if (returnObj == null) {
            returnObj = "";
        }

        /**
         *  生成一个发送对象
         */
        RabbitMetaMessage rabbitMetaMessage = new RabbitMetaMessage();

        rabbitMetaMessage.setMessageId(bizName);
        /**
         * 设置交换机
         */
        rabbitMetaMessage.setExchange(exchange);
        /**
         *  指定routing key
         */
        rabbitMetaMessage.setRoutingKey(bindingKey);
        /**
         * 设置需要传递的消息体,可以是任意对象
         */
        rabbitMetaMessage.setPayload(returnObj);

        /**
         * 将消息设置为ready状态
         */
        coordinator.setMsgReady(bizName, rabbitMetaMessage);

        /**
         * 发送消息
         */
        try {
            transRabbitSender.setCorrelationData(dbCoordinator);
            transRabbitSender.send(rabbitMetaMessage);

            /**
             * 消息发送成功，删除ready状态消息
             */
            coordinator.setMsgSuccess(bizName);
        } catch (Exception e) {
            // TODO logger.error("第一阶段消息发送异常" + bizName + e);
            throw e;
        }
    }

    public static String getCurrentDateTime() {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return df.format(new Date());
    }
}
